home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <stdio.h>
- #include "sw.h"
- #include "extern.h"
- #include "hud.h"
- #include "main.h"
- #include "explode.h"
- #include "ship.h"
- #include <Inventor/actions/SoGLRenderAction.h>
- #include <Inventor/events/SoMouseButtonEvent.h>
- #include <Inventor/events/SoLocation2Event.h>
- #include <Inventor/actions/SoAction.h>
- #include <Inventor/SoEventCallback.h>
- #include <Inventor/nodes/SoCallback.h>
- #include <gl/gl.h>
- #include <gl/glws.h>
-
- #define SELFEXPLODENUM 4
-
- struct ObjectNumber {
- public:
- int player;
- int subobject;
- float z;
- float t;
- };
-
- static ObjectNumber explosionList[MAXPLAYERS * (MAXMISSILES + 1)];
- static short selfExplodePos[SELFEXPLODENUM][2];
- static int hudColorState;
- static int hudFrameNumber = -1;
-
- static void drawExplosions()
- {
- // get list of explosions
- short numExplosions = 0;
- for (int i = 0; i < MAXPLAYERS; i++) {
- ShipObject* s = getPlayer(i);
- if (!s || s->active() != ObjectActive) continue;
- ShipInfo& si = s->shipInfo();
- if (playerView[i][0].visible && playerView[i][0].exploding) {
- explosionList[numExplosions].player = i;
- explosionList[numExplosions].subobject = 0;
- explosionList[numExplosions].z = playerView[i][0].lp[2];
- explosionList[numExplosions].t = si.info.explodeTime;
- numExplosions++;
- }
- for (int j = 0; j < MAXMISSILES; j++) {
- if (si.missile[j].active != ObjectActive) continue;
- if (playerView[i][j+1].visible && playerView[i][j+1].exploding) {
- explosionList[numExplosions].player = i;
- explosionList[numExplosions].subobject = j+1;
- explosionList[numExplosions].z = playerView[i][j+1].lp[2];
- explosionList[numExplosions].t = si.missile[j].explodeTime;
- numExplosions++;
- }
- }
- }
- if (numExplosions == 0) return; // nothing to draw
-
- // sort explosions back to front
- ObjectNumber tmp;
- for (i = 0; i < numExplosions-1; i++)
- for (int j = 1; j < numExplosions-i; j++)
- if (explosionList[j].z < explosionList[j-1].z) {
- tmp = explosionList[j-1];
- explosionList[j-1] = explosionList[j];
- explosionList[j] = tmp;
- }
-
- // draw explosions
- ortho(-0.5, viewScreenSize()[0] - 0.5, -0.5, viewScreenSize()[1] - 0.5,
- -1.0, 1.0);
- zwritemask(0);
- blendfunction(BF_SA, BF_MSA);
- for (i = 0; i < numExplosions; i++) {
- int p = explosionList[i].player, s = explosionList[i].subobject;
- float z = (-playerView[p][s].lp[2] * (YONPLANE + HITHERPLANE) -
- 2.0 * HITHERPLANE * YONPLANE) /
- (-playerView[p][s].lp[2] * (YONPLANE - HITHERPLANE));
- drawExplosion(playerView[p][s].p[0], playerView[p][s].p[1],
- playerView[p][s].r, z, explosionList[i].t);
- }
- blendfunction(BF_ONE, BF_ZERO);
- zwritemask(0xffffffff);
- }
-
- static void drawSelfExplosion()
- {
- ortho(-0.5, viewScreenSize()[0] - 0.5, -0.5, viewScreenSize()[1] - 0.5,
- -1.0, 1.0);
- zwritemask(0);
- blendfunction(BF_SA, BF_MSA);
- for (int i = 0; i < SELFEXPLODENUM; i++)
- drawExplosion(selfExplodePos[i][0], selfExplodePos[i][1],
- viewScreenSize()[1], -0.999, myShip->explodeTime());
- blendfunction(BF_ONE, BF_ZERO);
- zwritemask(0xffffffff);
- }
-
- static void drawHud(void*)
- {
- if (!isPaused() && frameNumber == hudFrameNumber) // avoid extra redraws
- return;
- hudFrameNumber = frameNumber;
-
- // set up GL context
- GLXwinset(display, view->getNormalWindow());
- font(0);
- short fh = (short)getheight() - (short)getdescender();
-
- // draw all explosions
- drawExplosions();
- if (myShip->exploding()) drawSelfExplosion();
-
- if (hudColorState != 0) { // if want it drawn
-
- short cx = viewScreenSize()[0], cy = viewScreenSize()[1];
- ortho2(-0.5, cx - 0.5, -0.5, cy - 0.5);
-
- // set HUD color
- switch (hudColorState) {
- case 1: cpack(0xff00ff00); break;
- case 2: cpack(0xff008000); break;
- }
-
- // draw center cross hair
- cx >>= 1;
- cy >>= 1;
- short x = cx, y = cy;
- sboxs(x - 10, y, x - 20, y);
- sboxs(x + 10, y, x + 20, y);
- sboxs(x, y - 10, x, y - 20);
- sboxs(x, y + 10, x, y + 20);
-
- // draw tracking cross hairs
- SbVec2s trackingPos;
- getViewPosition(myShip->trackDirection(), trackingPos);
- x = trackingPos[0];
- y = trackingPos[1];
- short v[2];
- bgnclosedline();
- v[0] = x + 12; v[1] = y + 12; v2s(v);
- v[0] = x + 6; v[1] = y + 6; v2s(v);
- endclosedline();
- bgnclosedline();
- v[0] = x + 12; v[1] = y - 12; v2s(v);
- v[0] = x + 6; v[1] = y - 6; v2s(v);
- endclosedline();
- bgnclosedline();
- v[0] = x - 12; v[1] = y - 12; v2s(v);
- v[0] = x - 6; v[1] = y - 6; v2s(v);
- endclosedline();
- bgnclosedline();
- v[0] = x - 12; v[1] = y + 12; v2s(v);
- v[0] = x - 6; v[1] = y + 6; v2s(v);
- endclosedline();
-
- // is fps display on then show fps
- if (isFpsOn()) {
- char buf[10];
- sprintf(buf, "%d", getFps());
- cmov2s(cx - 100, cy - 104 - fh);
- charstr(buf);
- }
-
- // get target info
- int target = currentTarget();
- ShipObject* tObj = (target == -1) ? NULL : getTarget(target);
- float th, tp;
- if (tObj) {
- SbVec3f td = tObj->position();
- td -= myShip->position();
- th = atan2(td[2], td[0]) * 180.0 / M_PI;
- if (th < 0.0) th += 360.0;
- tp = asin(td[1] / td.length()) * 180.0 / M_PI;
- }
-
- // draw heading and pitch meters
- float a;
- short am, ai;
- char num[4];
-
- // draw heading meter
- a = atan2(myShip->direction()[2], myShip->direction()[0]) * 180.0 / M_PI;
- if (a < 0.0) a += 360.0;
- am = (short)(a/30) - 1;
- if (am < 0) am += 12;
- pushviewport();
- scrmask(cx - 100, cx + 100, cy + 105, cy + 130);
- sboxs(cx, cy + 105, cx, cy + 110);
- pushmatrix();
- translate(cx - ((short)(a*3) % 90), cy + 110, 0.0);
- for (short i = -90; i <= 180; i += 90) { // tick marks
- sboxs(i, 0, i, 5);
- sboxs(i+30, 0, i+30, 3);
- sboxs(i+60, 0, i+60, 3);
- }
- for (i = 0; i <= 3; i++) { // degree labels
- sprintf(num, "%d", ((am+i) * 30) % 360);
- cmov2s(90 * i - (short)(strwidth(num) >> 1) - 90, 7);
- charstr(num);
- }
-
- // if there is a target draw it's heading as a diamond
- if (target != -1) {
- translate((short)(a*3) % 90, 0.0, 0.0);
- short tx = short(3.0 * (th - a));
- if (tx < 3 * -180) tx += 3 * 360;
- else if (tx > 3 * 180) tx -= 3 * 360;
- if (tx < 95) { // draw left pointing arrow
- bgnpolygon();
- v[0] = (tx < -95) ? -95 : tx; v[1] = 10; v2s(v);
- v[0] -= 5; v[1] = 5; v2s(v);
- v[0] += 5; v[1] = 0; v2s(v);
- endpolygon();
- }
- if (tx > -95) { // draw right pointing arrow
- bgnpolygon();
- v[0] = (tx > 95) ? 95 : tx; v[1] = 0; v2s(v);
- v[0] += 5; v[1] = 5; v2s(v);
- v[0] -= 5; v[1] = 10; v2s(v);
- endpolygon();
- }
- }
- popmatrix();
-
- // draw pitch meter
- a = asin(myShip->direction()[1]) * 180.0 / M_PI;
- am = (short)(a/10);
- scrmask(cx - 150, cx - 105, cy - 100, cy + 100);
- sboxs(cx - 110, cy, cx - 105, cy);
- pushmatrix();
- translate(cx - 110, cy - ((short)(a*5) % 50), 0.0);
- for (ai = am - 3, i = -150; i <= 100; ai++, i += 50) {
- if (ai < -9 || ai > 9) continue;
- sboxs(-5, i, 0, i);
- if (ai == 9) continue;
- sboxs(-3, i+10, 0, i+10);
- sboxs(-3, i+20, 0, i+20);
- sboxs(-3, i+30, 0, i+30);
- sboxs(-3, i+40, 0, i+40);
- }
- for (ai = am - 2, i = -2; i <= 3; ai++, i++) {
- if (ai < -9 || ai > 9) continue;
- sprintf(num, "%d", ai * 10);
- cmov2s(-7 - (short)strwidth(num), 50 * i - (fh >> 1));
- charstr(num);
- }
-
- // if there is a target draw it's heading as a diamond
- if (target != -1) {
- translate(0.0, (short)(a*5) % 50, 0.0);
- short ty = short(5.0 * (tp - a));
- if (ty < 5 * -90) ty += 5 * 180;
- else if (ty > 5 * 90) ty -= 5 * 180;
- if (ty < 95) { // draw down pointing arrow
- bgnpolygon();
- v[0] = -10; v[1] = (ty < -95) ? -95 : ty; v2s(v);
- v[0] = -5; v[1] -= 5; v2s(v);
- v[0] = 0; v[1] += 5; v2s(v);
- endpolygon();
- }
- if (ty > -95) { // draw up pointing arrow
- bgnpolygon();
- v[0] = 0; v[1] = (ty > 95) ? 95 : ty; v2s(v);
- v[0] = -5; v[1] += 5; v2s(v);
- v[0] = -10; v[1] -= 5; v2s(v);
- endpolygon();
- }
- }
- popmatrix();
- popviewport();
-
- // draw targeting boxes around all potential targets
- SbVec3f ltd, td;
- SbVec2s p;
- for (int j = 1; j < MAXPLAYERS; j++) {
- ShipObject* s = getPlayer(j);
- if (!s) continue;
- if (s->shipVisibility()) {
- if (tObj == s) {
- rects(playerView[j][0].p[0] - 12,
- playerView[j][0].p[1] - 12,
- playerView[j][0].p[0] + 12,
- playerView[j][0].p[1] + 12);
- rects(playerView[j][0].p[0] - 11,
- playerView[j][0].p[1] - 11,
- playerView[j][0].p[0] + 11,
- playerView[j][0].p[1] + 11);
- }
- else {
- rects(playerView[j][0].p[0] - 6,
- playerView[j][0].p[1] - 6,
- playerView[j][0].p[0] + 6,
- playerView[j][0].p[1] + 6);
- rects(playerView[j][0].p[0] - 5,
- playerView[j][0].p[1] - 5,
- playerView[j][0].p[0] + 5,
- playerView[j][0].p[1] + 5);
- }
- }
- }
-
- // draw missile lock diamond
- if (missileLock.visible) {
- v[0] = missileLock.p[0] + cx;
- v[1] = missileLock.p[1] + cy;
- bgnline();
- v[1] -= missileLock.r; v2s(v);
- v[0] += missileLock.r; v[1] += missileLock.r; v2s(v);
- v[0] -= missileLock.r; v[1] += missileLock.r; v2s(v);
- v[0] -= missileLock.r; v[1] -= missileLock.r; v2s(v);
- v[0] += missileLock.r; v[1] -= missileLock.r; v2s(v);
- endline();
- bgnclosedline();
- v[1] += 1; v2s(v);
- v[0] += missileLock.r - 1; v[1] += missileLock.r - 1; v2s(v);
- v[0] -= missileLock.r - 1; v[1] += missileLock.r - 1; v2s(v);
- v[0] -= missileLock.r - 1; v[1] -= missileLock.r - 1; v2s(v);
- endclosedline();
- }
-
- // set HUD color for missile boxes
- switch (hudColorState) {
- case 1: cpack(0xff00c0ff); break;
- case 2: cpack(0xff006080); break;
- }
-
- // draw boxes around all missiles that aren't mine
- for (j = 1; j < MAXPLAYERS; j++) {
- ShipObject* s = getPlayer(j);
- if (!s) continue;
- for (int k = 0; k < MAXMISSILES; k++) {
- if (s->missileVisibility(k)) {
- rects(playerView[j][k+1].p[0] - 6,
- playerView[j][k+1].p[1] - 6,
- playerView[j][k+1].p[0] + 6,
- playerView[j][k+1].p[1] + 6);
- rects(playerView[j][k+1].p[0] - 5,
- playerView[j][k+1].p[1] - 5,
- playerView[j][k+1].p[0] + 5,
- playerView[j][k+1].p[1] + 5);
- }
- }
- }
-
- // set HUD color for team flag boxes
- switch (hudColorState) {
- case 1: cpack(0xffffffff); break;
- case 2: cpack(0xff808080); break;
- }
-
- // draw boxes around team flags that are floating free
- for (j = 0; j < NUMTEAMS; j++) {
- if (getTeam(Team(j)).state == FlagReady && flagView[j].visible) {
- rects(flagView[j].p[0] - 6,
- flagView[j].p[1] - 6,
- flagView[j].p[0] + 6,
- flagView[j].p[1] + 6);
- rects(flagView[j].p[0] - 5,
- flagView[j].p[1] - 5,
- flagView[j].p[0] + 5,
- flagView[j].p[1] + 5);
- }
- }
-
- }
-
- if (myShip->active() != ObjectActive) {
- short fy = short(getheight());
- short y = viewScreenSize()[1] - 4 - fh;
- cpack(0xffffffff);
-
- if (myShip->active() == ObjectInactive) {
- cmov2s(4, y);
- charstr("Press space bar to begin");
- y -= 2 * fy;
- }
- else {
- cmov2s(4, y);
- charstr("Press \'p\' to resume");
- y -= 2 * fy;
- }
-
- cmov2s(500, y);
- charstr("Individual");
- cmov2s(700, y);
- charstr("Team");
-
- y -= fy;
- cmov2s(4, y);
- charstr("Player");
- cmov2s(250, y);
- charstr("Team");
- cmov2s(350, y);
- charstr("Ship");
- cmov2s(450, y);
- charstr("Won");
- cmov2s(500, y);
- charstr("Lost");
- cmov2s(550, y);
- charstr("Score");
- cmov2s(650, y);
- charstr("Won");
- cmov2s(700, y);
- charstr("Lost");
- cmov2s(750, y);
- charstr("Score");
-
- y -= fy >> 1;
- char buf[20];
- for (int i = 0; i < MAXPLAYERS; i++) {
- ShipObject* s = getPlayer(i);
- if (!s) continue;
- y -= fy;
-
- cmov2s(4, y);
- charstr(s->name());
- cmov2s(250, y);
- charstr(teamName(s->team()));
- cmov2s(350, y);
- charstr(shipClassName(s->shipClass()));
-
- sprintf(buf, "%d", s->won());
- cmov2s(450, y);
- charstr(buf);
- sprintf(buf, "%d", s->lost());
- cmov2s(500, y);
- charstr(buf);
- sprintf(buf, "%d", s->score());
- cmov2s(550, y);
- charstr(buf);
-
- sprintf(buf, "%d", getTeam(s->team()).won);
- cmov2s(650, y);
- charstr(buf);
- sprintf(buf, "%d", getTeam(s->team()).lost);
- cmov2s(700, y);
- charstr(buf);
- sprintf(buf, "%d", getTeam(s->team()).won - getTeam(s->team()).lost);
- cmov2s(750, y);
- charstr(buf);
- }
- }
- }
-
- static void hudAction(void* data, SoAction* action)
- {
- if (action->getTypeId() == SoGLRenderAction::getClassTypeId())
- drawHud(data);
- }
-
- static void setAngularVelocity(const SbVec2s& p)
- {
- // we're copying p[0] and p[1] to px and py here to avoid modifying
- // a const... christine
- short px, py;
-
- px = p[0];
- py = p[1];
-
- // handle zero motion areas in center
- short cx = viewScreenSize()[0] >> 1, cy = viewScreenSize()[1] >> 1;
- if (px - cx < -10) px += 10;
- else if (px - cx > 10) px -= 10;
- else px = cx;
- if (py - cy < -10) py += 10;
- else if (py - cy > 10) py -= 10;
- else py = cy;
-
- // set target angular velocity
- // move px and py into pp ... christine
- SbVec2s pp(px,py);
-
- SbVec3f avd;
- getViewDirection(pp, avd);
- myShip->targetAngVel(avd);
- }
-
- static void hudMouseButtonEvent(void*, SoEventCallback* ec)
- {
- SoMouseButtonEvent* e = (SoMouseButtonEvent*)(ec->getEvent());
-
- if (SO_MOUSE_PRESS_EVENT(e, BUTTON1)) {
- switch (currentWeapon()) {
- case Laser:
- myShip->fireLaser();
- break;
- case Missile:
- if (currentTarget() == -1 || !missileLock.visible || missileLock.r!=16)
- myShip->fireMissile(NULL);
- else {
- ShipObject* s = getTarget(currentTarget());
- ShipInfo& si = s->shipInfo();
- myShip->fireMissile(&(si.info));
- }
- break;
- }
- }
- else if (SO_MOUSE_PRESS_EVENT(e, BUTTON3)) {
- setAngularVelocity(e->getPosition());
- }
-
- ec->setHandled();
- }
-
- static void hudLocation2Event(void*, SoEventCallback* ec)
- {
- SoLocation2Event* e = (SoLocation2Event*)(ec->getEvent());
-
- // set tracking box target location
- SbVec3f td;
- getViewDirection(e->getPosition(), td);
- myShip->trackDirection(td);
-
- // if right down, set new angular velocity
- if (buttonPressed[RightMouseButton]) {
- setAngularVelocity(e->getPosition());
- }
-
- ec->setHandled();
- }
-
- void makeHud()
- {
- hudColorState = 1;
-
- // get mouse and keyboard events in the head's up display
- SoEventCallback* hudEventCallback = new SoEventCallback;
- hudEventCallback->addEventCallback(SoMouseButtonEvent::getClassTypeId(),
- hudMouseButtonEvent);
- hudEventCallback->addEventCallback(SoLocation2Event::getClassTypeId(),
- hudLocation2Event);
- universe->insertChild(hudEventCallback, 0); // get 'em quick
-
- // add action callback to hud action routine
- SoCallback* hudCallback = new SoCallback;
- hudCallback->setCallback(hudAction);
- universe->addChild(hudCallback); // draw hud last
- }
-
- #include <X11/Xirisw/GlxMDraw.h>
- static GLXconfig hudConfig[] = { {GLX_NORMAL, GLX_STENSIZE, 1},
- {0, 0, 0} };
-
- void hudReset()
- {
- // enable stencil planes in HUD
- GLXconfig* c = GLXgetconfig(view->getDisplay(),
- XScreenNumberOfScreen(XtScreen(view->getWidget())),
- hudConfig);
- XtVaSetValues(view->getWidget(), GlxNglxConfig, c, NULL);
- GLXwinset(display, view->getNormalWindow());
- sclear(0);
-
- for (int i = 0; i < SELFEXPLODENUM; i++) {
- selfExplodePos[i][0] = short(viewScreenSize()[0] * (0.25+0.5*drand48())),
- selfExplodePos[i][1] = short(viewScreenSize()[1] * (0.25+0.5*drand48()));
- }
- }
-
- void nextHudColor()
- {
- if (++hudColorState > 2) hudColorState = 0;
- }
-